home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / tnftpsr / tnsub1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-14  |  50.5 KB  |  1,898 lines

  1. /*     ANS compatible Telnet in AES windows     */
  2. /*         compiled with TURBO-C/PURE-C         */
  3. /*  P. Mayer & H. Wieser fortec TU Vienna 1992  */
  4.  
  5. #include <vdi.h>
  6. #include <aes.h>
  7. #include <tos.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "tnftp.h"
  12. #include "tndefs.h"
  13.  
  14. extern char *getmem(long size);
  15. extern int w_open(char *name, int xpos, int ypos, int xsiz, int ysiz, int sliders, int titles, FNT *usefont);
  16. extern void w_closei(struct wi_str *wp);
  17. extern void w_close(struct wi_str *wp);
  18. extern int w_resize(struct wi_str *wp1, int xsiz, int ysiz, int sliders, int titles, int chfont);
  19. extern void w_rename(struct wi_str *wp, char *name);
  20. extern void w_info(struct wi_str *wp, char *name);
  21. extern void w_redraw(struct wi_str *wp, int logic, int xx, int yy, int ww, int hh);
  22. extern void w_update(struct wi_str *wp, int logic, int xx, int yy, int ww, int hh);
  23. extern void w_move(struct wi_str *wp, int xx, int yy, int ww, int hh);
  24. extern void w_top(struct wi_str *wp);
  25. extern void w_bottom(void);
  26. extern void w_hide(void);
  27. extern void w_shrink(struct wi_str *wp);
  28. extern void w_full(struct wi_str *wp);
  29. extern void w_arrow(struct wi_str *wp, int arrow);
  30. extern void w_slide(struct wi_str *wp, int hor, int val);
  31. extern void sethslide(struct wi_str *wp);
  32. extern void w_output(struct wi_str *wp, unsigned char *ptr, short charcount);
  33. extern void lineerase(register struct wi_str *wp, int first, int last);
  34. extern int tcp_out(int tcp_id, char *o_str, int o_len);
  35. extern int do_multi(int);
  36.  
  37. void setvslide(struct wi_str *wp);
  38. void w_flash(struct wi_str *wp, int state);
  39. void scrollup(register struct wi_str *wp, int first, int nlines, int amount);
  40. void scrolldn(register struct wi_str *wp, int first, int nlines, int amount);
  41. int rc_intersect( GRECT *r1, GRECT *r2 );
  42. void vt100_reset (struct wi_str *wp);
  43.  
  44. /* variables used by various routines
  45.  */
  46.  
  47. extern int screen_handle;
  48. extern  long dummy;  /* dummy return variable */
  49. extern    int sdummy;  /* short-sized dummy */
  50.  
  51. extern    int    scr_x, scr_y;  /* size of the screen */
  52. extern    int    scr_w, scr_h;
  53. extern    int    fast;
  54. extern  int    wrap;
  55. /* this makes more updates happen in "scrolled" mode with delayed updates */
  56. extern    int    jerky_updates;
  57. extern    int    mouseflicker;  /* for knowing when to turn it on */
  58. extern    int    audibell;  /* What happens on BEL? */
  59. extern    int    visibell;
  60.  
  61. extern    FNT    *curfont;  /* current font */
  62. extern    WIN_MFDB screen_mf;  /* screen descriptor */
  63. extern    int    mouse;  /* for mouse on/off */
  64.  
  65. extern  struct wi_str *wlist;
  66.  
  67. extern int ncolors;  /* used by ESCb and ESCc */
  68. extern int o_len;
  69. extern char o_str[30];
  70.  
  71. /* the program code... */
  72.  
  73. static BASPAG **oldpd;
  74.  
  75. long set_pd(void)
  76. {
  77.   oldpd = SYSBASE->_run;
  78.   SYSBASE->_run = &_BasPag;
  79.   return 0;
  80. }
  81.  
  82. long restore_pd(void)
  83. {
  84.   SYSBASE->_run = oldpd;
  85.   return 0;
  86. }
  87.  
  88. char *getmem(size)
  89. register long size;
  90. {
  91.   char *got;
  92.  
  93.   /* this relies on malloc taking size_t, and size_t being long, */
  94.   /* or else not compiling with -mshort */
  95. /*  Supexec(set_pd);*/
  96.   got = (char *) malloc(size);
  97. /*  Supexec(restore_pd);*/
  98.   if (got == NULL) 
  99.   {
  100.     form_alert(1, "[1][Out of memory][ Ok ]");
  101.   }
  102.   else 
  103.   {
  104.     memset(got, 0, size);
  105.   }
  106.   return got;
  107. }
  108.  
  109. /*
  110.  * w_open opens a window with the supplied name.  The new window is
  111.  * top, ergo wlist.  Puts up an alert & returns -1 on errors.
  112.  */
  113.  
  114. int w_open(name, xpos, ypos, xsiz, ysiz, sliders, titles, usefont)
  115. char *name;
  116. int xpos, ypos, xsiz, ysiz;
  117. int sliders, titles;  /* nonzero to get that thing */
  118. FNT *usefont;  /* ptr to font to use */
  119. {
  120.   register struct wi_str *wp;
  121.   int wdes;
  122.   int wtyp;
  123.   int tmp_w, tmp_h; 
  124.  
  125.   wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_WITHTITLE : 0);
  126.   if (ypos < scr_y) ypos = scr_y;
  127.   if (xpos < scr_x) xpos = scr_x;
  128.  
  129.   wind_calc(0, wtyp, 0, 0, usefont->inc_x*xsiz+2*X0,
  130.   usefont->inc_y*ysiz+2*Y0, &sdummy, &sdummy, &tmp_w, &tmp_h);
  131.  
  132.   if (tmp_w>scr_w)
  133.     tmp_w = scr_w;  /* full size <= screen size */
  134.  
  135.   if (tmp_h>scr_h)
  136.     tmp_h = scr_h;
  137.  
  138.   wp = (struct wi_str *)getmem(sizeof(struct wi_str));
  139.   if (wp == NULL) 
  140.   {
  141.     return -1;
  142.   }
  143.  
  144.   wp->wi_mf.wpix = 2*X0 + xsiz*usefont->inc_x;
  145.   wp->wi_mf.hpix = 2*Y0 + ysiz*usefont->inc_y;
  146.   wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
  147.   wp->wi_mf.planes = 1;
  148.   wp->font = usefont;
  149.   wp->fgbg[1] = 0;  /* foreground color for vrt_copyfm */
  150.   wp->fgbg[0] = 1;  /* background color for vrt_copyfm */
  151.   wp->discard = !wrap;
  152.   wp->recv_flag = 1;
  153.   /* allocate a screen image for this window before wind_create */
  154.   wp->wi_mf.ptr = (short *)getmem(
  155.   ((long)wp->wi_mf.hpix + wp->font->inc_y*MAXSCROLLED) * 
  156.       wp->wi_mf.wwords*2);
  157.  
  158.   if (wp->wi_mf.ptr == NULL) 
  159.   {
  160.     free(wp);
  161.     return -1;
  162.   }
  163.   wdes = wind_create(wtyp, scr_x, scr_y, tmp_w, tmp_h);
  164.   if (wdes < 0) 
  165.   {
  166.     form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
  167.     free(wp->wi_mf.ptr);
  168.     free(wp);
  169.     return -1;
  170.   }
  171.  
  172.   /* install at head of wlist list (which is sorted by window depth) */
  173.   if (wlist == NULL) 
  174.   {
  175.     wp->next = wp->prev = wp;
  176.   }
  177.   else 
  178.   {
  179.     wp->next = wlist;
  180.     wp->prev = wlist->prev;
  181.     wlist->prev->next = wp;
  182.     wlist->prev = wp;
  183.   }
  184.   wlist = wp;
  185.  
  186.   wp->sliders = sliders;
  187.   wp->titles = titles;
  188.   wp->aes_handle = wdes;
  189.   wp->wi_w = X0*2 + usefont->inc_x*xsiz;
  190.   wp->wi_h = Y0*2 + usefont->inc_y*ysiz;
  191.   wp->wi_style = wtyp;
  192.   wp->wi_mainstyle = wtyp;
  193.  
  194.   w_rename(wp, name);
  195.   w_info(wp, "");
  196.  
  197.   if (!fast)
  198.     graf_growbox(0, 0, 20, 10, xpos, ypos, tmp_w, tmp_h);
  199.   wind_open(wdes, xpos, ypos, tmp_w, tmp_h);
  200.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  201.  
  202.   wp->fulled = 0;
  203.   wp->x_off = 0;
  204.   wp->y_off = 0;
  205.   wp->px_off = 0;
  206.   wp->py_off = 0;
  207.   wp->m_off = wp->x & 15;  /* when is this used? */
  208.   wp->cur_x = X0;
  209.   wp->cur_y = Y0;
  210.   wp->top_y = Y0;
  211.   wp->x_chrs = xsiz;
  212.   wp->y_chrs = ysiz;
  213.  
  214.   setvslide(wp);
  215.   sethslide(wp);
  216.   w_redraw(wp,FM_COPY, wp->x, wp->y, wp->w, wp->h);
  217.   vt100_reset(wp);
  218.   wlist->markx1 = wlist->markx2 = wlist->lastx2 = -1;
  219.   wlist->marky1 = wlist->marky2 = wlist->lasty2 = -1;
  220.   wlist->direct = 0;
  221.   return 0;
  222. }
  223.  
  224. /*
  225.  * w_closei removes a window but does not release its storage.  This is used
  226.  * if the window contents must be saved for later use.
  227.  */
  228. void w_closei(wp)
  229. struct wi_str *wp;
  230. {
  231.   int xx, yy, ww, hh;
  232.   int wdes = wp->aes_handle;
  233.  
  234.   wind_get(wdes, WF_CURRXYWH, &xx, &yy, &ww, &hh);
  235.   wind_close(wdes);
  236.   if (!fast)
  237.     graf_shrinkbox(0, 0, 20, 10, xx, yy, ww, hh);
  238.   wind_delete(wdes);
  239. }
  240.  
  241. /*
  242.  * w_close removes a window.
  243.  */
  244. void w_close(wp)
  245. struct wi_str *wp;
  246. {
  247.   /* unlink me */
  248.   wp->prev->next = wp->next;
  249.   wp->next->prev = wp->prev;
  250.   if (wp->next == wp) wlist = NULL;  /* singleton list */
  251.   else if (wlist == wp) wlist = wp->next;
  252.  
  253.   w_closei(wp);
  254.   free(wp->wi_mf.ptr);
  255.   free(wp);
  256. }
  257.  
  258. /* w_resize resizes an existing window.  Also lets you pass in the
  259.  * sliders & titles arguments for the newly-sized window.
  260.  *
  261.  * This used to relocate the window; now it copies the xy.
  262.  * This used to change the font in the window; now it doesn't unless
  263.  * chfont == 1.
  264.  */
  265. int w_resize(wp1, xsiz, ysiz, sliders, titles, chfont)
  266. struct wi_str *wp1;
  267. int xsiz, ysiz;
  268. int sliders, titles;
  269. int chfont;  /* flag: when 0 don't change font */
  270. {
  271.   struct wi_str *wp2;
  272.   static int c[8];
  273.   int tmp_x, tmp_y, tmp_w, tmp_h, wtyp;
  274.   int retcode;
  275.  
  276.   if (wp1->curstate) 
  277.   {
  278.     w_flash(wp1,0);
  279.   }
  280.  
  281.   w_closei(wp1);  /* close it (closes AES window) */
  282.  
  283.             /* what's happening here is that the overlap of screen images between
  284.              * the old & new sizes gets copied into the new window. This is done by
  285.              * deleting the old window, creating a new one of the new size, and
  286.              * copying the appropriate rectangle of screen image over.
  287.              */
  288.  
  289.   /* unlink me */
  290.   wp1->prev->next = wp1->next;
  291.   wp1->next->prev = wp1->prev;
  292.   if (wp1->next == wp1) wlist = NULL;
  293.   else if (wlist == wp1) wlist = wp1->next;
  294.  
  295.   wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_WITHTITLE : 0);
  296.   wind_calc(0,wtyp,wp1->x,wp1->y,wp1->w,wp1->h,
  297.   &tmp_x, &tmp_y, &tmp_w, &tmp_h);
  298.  
  299.   /* open this window with the same workxy as the previous */
  300.   if (w_open(wp1->name, tmp_x, tmp_y, xsiz, ysiz, 
  301.   sliders, titles, (chfont ? curfont : wp1->font))) 
  302.   {
  303.     /* error opening the new copy of the window */
  304.     retcode = -1;
  305.     goto freeold;
  306.   }
  307.  
  308.   wp2 = wlist;
  309.   c[0] = wp1->m_off;
  310.   c[1] = wp1->top_y + max(0, wp1->wi_mf.hpix - wp2->wi_mf.hpix);
  311.   c[2] = c[0] + min(wp1->wi_mf.wpix, wp2->wi_mf.wpix);
  312.   c[3] = c[1] + min(wp1->wi_mf.hpix, wp2->wi_mf.hpix);
  313.   c[4] = wp2->m_off;
  314.   c[5] = wp2->top_y;
  315.   c[6] = c[4] + min(wp1->wi_mf.wpix, wp2->wi_mf.wpix);
  316.   c[7] = c[5] + min(wp1->wi_mf.hpix, wp2->wi_mf.hpix);
  317.  
  318.   /* copy screen */
  319.   vro_cpyfm(screen_handle, FM_COPY, c, (MFDB*)&wp1->wi_mf, (MFDB*)&wp2->wi_mf);
  320.   /* copy parameters */
  321.  
  322.   wp2->fgbg[0] = wp1->fgbg[0];
  323.   wp2->fgbg[1] = wp1->fgbg[1];
  324.   wp2->insmode = wp1->insmode;
  325.  
  326.   wp2->fd = wp1->fd;
  327.   wp2->pid = wp1->pid;
  328.  
  329.   if (wtyp != wp1->wi_mainstyle) 
  330.   {
  331.     /* you're changing the style... copy mainstyle from the original */
  332.     wp2->wi_mainstyle = wp1->wi_mainstyle;
  333.   }
  334.  
  335.           /* if font changed, put cursor at bottom left.  Else put it at old X
  336.            * offset (or right edge if narrower than that), and I can't figure out
  337.            * the calculation for Y.
  338.            */
  339.   if (wp2->font != wp1->font) 
  340.   {
  341.     wp2->cur_x = X0;
  342.     wp2->cur_y = (wp2->y_chrs - 1) * wp2->font->inc_y + Y0;
  343.   }
  344.   else 
  345.   {
  346.     wp2->cur_x = (wp2->x_chrs - 1) * wp2->font->inc_x + X0;
  347.     if (wp1->cur_x < wp2->cur_x)
  348.       wp2->cur_x = wp1->cur_x;
  349.     wp2->cur_y = max(0, wp1->cur_y - c[1]) + Y0;
  350.   }
  351.   
  352.   wp2->state = wp1->state;
  353.   strcpy(wp2->name,wp1->name);
  354.  
  355.   wp2->discard = wp1->discard; /* was commented out */
  356.   wp2->curskey = wp1->curskey;
  357.   wp2->keypad = wp1->keypad;
  358.   wp2->smooth = wp1->smooth;
  359.   wp2->repeat = wp1->repeat;
  360.   wp2->lfmode = wp1->lfmode;
  361.   
  362.   wp2->G0 = wp1->G0;
  363.   wp2->G1 = wp1->G1;
  364.   wp2->chset = wp1->chset;
  365.   
  366.   wp2->app = wp1->app;
  367.   wp2->recv_flag = wp1->recv_flag;
  368.   wp2->ftp_data = wp1->ftp_data;
  369.  
  370.   w_flash(wp2,wp1->curstate);
  371.   retcode = 0;
  372.  
  373. freeold:
  374.   free(wp1->wi_mf.ptr);
  375.   free(wp1);
  376.   return retcode;  /* old window is GONE if this is -1 */
  377. }
  378.  
  379. /* w_rename changes the title bar of a window
  380.  */
  381. void w_rename(wp, name)
  382. struct wi_str *wp;
  383. char *name;
  384. {
  385.   if (name)
  386.     strcpy(wp->name, name);
  387.   if (wp->wi_style & NAME) 
  388.   {
  389.     wind_set(wp->aes_handle, WF_NAME, wp->name, 0, 0);
  390.   }
  391. }
  392. /* w_info changes the info line of a window
  393.  */
  394. void w_info(wp, name)
  395. struct wi_str *wp;
  396. char *name;
  397. {
  398.   if (name)
  399.     strcpy(wp->info, name);
  400.   if (wp->wi_style & NAME) 
  401.   {
  402.     wind_set(wp->aes_handle, WF_INFO, wp->info, 0, 0);
  403.   }
  404. }
  405.  
  406. /* w_redraw redraws part of the screen from window contents.
  407.  * The coordinates are screen relative.
  408.  */
  409. void w_redraw(wp, logic, xx, yy, ww, hh)
  410. struct wi_str *wp;
  411. int logic,xx,yy,ww,hh;
  412. {
  413.   int c[8];
  414.   GRECT t1, t2;
  415.   int wdes = wp->aes_handle;
  416.  
  417.   /* turn vro_cpyfm logic ops into vrt_cpyfm ones */
  418.   if (logic == FM_INVERT) logic = 3;
  419.   else logic = 1;
  420.  
  421.   if (xx+ww > scr_w)
  422.     ww = scr_w - xx;
  423.   if (yy+hh > scr_h+scr_y)
  424.     hh = scr_h+scr_y - yy;
  425.   t2.g_x = xx; 
  426.   t2.g_y = yy;
  427.   t2.g_w = ww; 
  428.   t2.g_h = hh;
  429.   t1.g_x = wp->x; 
  430.   t1.g_y = wp->y;
  431.   t1.g_w = wp->w; 
  432.   t1.g_h = wp->h;
  433.   if (!rc_intersect(&t2, &t1)) 
  434.   {
  435.     return;  /* nothing to do... */
  436.   }
  437.   wind_update(TRUE);
  438.   wind_get(wdes, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  439.   while (t1.g_w && t1.g_h) 
  440.   {
  441.     if (rc_intersect(&t2, &t1)) 
  442.     {
  443.       if (mouse) 
  444.       {
  445.         /* we have to do graphics, so switch the mouse off.
  446.                                      * mouse will be switched on again in main loop.
  447.                                      * this is ugly, but it improves speed a bit...
  448.                                      * (If mouseflicker is ON, we'll turn it on again below)
  449.                                      */
  450.         mouse = 0;
  451.         graf_mouse(M_OFF, NULL);
  452.       }
  453.       c[0] = t1.g_x - wp->x + wp->x_off + wp->m_off;
  454.       c[1] = t1.g_y - wp->y + wp->y_off + wp->top_y - Y0;
  455.       c[2] = c[0] + t1.g_w - 1;
  456.       c[3] = c[1] + t1.g_h - 1;
  457.       c[4] = t1.g_x;
  458.       c[5] = t1.g_y;
  459.       c[6] = c[4] + t1.g_w - 1;
  460.       c[7] = c[5] + t1.g_h - 1;
  461.       vrt_cpyfm(screen_handle, logic, c,
  462.       (MFDB*)&wp->wi_mf, (MFDB*)&screen_mf, wp->fgbg);
  463.     }
  464.     wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  465.   }
  466.   wind_update(FALSE);
  467.   /* mouse stays hidden -- we'll make it visible next time it moves */
  468.   /* except if mouseflicker is on, in which case we'll do it NOW */
  469.   if (!mouse && mouseflicker) 
  470.   {
  471.     mouse = 1;
  472.     graf_mouse(M_ON,NULL);
  473.   }
  474. }
  475.  
  476. /* w_update copies a portion of the window to the screen.  Coordinates
  477.  * are window-relative
  478.  */
  479. void w_update(wp, logic, xx, yy, ww, hh)
  480. struct wi_str *wp;
  481. int logic, xx,yy,ww,hh;
  482. {
  483.   w_redraw(wp, logic, xx + wp->x - wp->x_off, 
  484.   yy + wp->y - wp->y_off - wp->top_y + Y0, ww, hh);
  485. }
  486.  
  487. /* w_move sets the window's idea of its own position on the screen
  488.  */
  489.  
  490. void w_move(wp, xx, yy, ww, hh)
  491. struct wi_str *wp;
  492. int xx, yy, ww, hh;
  493. {
  494.   int wdes = wp->aes_handle;
  495.   int flag = 0;
  496.   int m_w, m_h;
  497.   int x1, x2;
  498.   int tmp;
  499.   int c[8];
  500.   int inc_x, inc_y;
  501.  
  502.   wind_calc(1, wp->wi_style, xx, yy, ww, hh, &sdummy, &sdummy, &m_w, &m_h);
  503.   if ((tmp = (m_w-2*X0)%wp->font->inc_x) != 0)
  504.   {
  505.     ww -= tmp;
  506.     m_w -= tmp;
  507.   }
  508.   if ((tmp = (m_h-2*Y0)%wp->font->inc_y) != 0)
  509.   {
  510.     hh -= tmp;
  511.     m_h -= tmp;
  512.   }
  513.   if (m_w>wp->wi_w) ww = ww-(m_w-wp->wi_w);
  514.   if (m_h>wp->wi_h) hh = hh-(m_h-wp->wi_h);
  515.   wind_set(wdes, WF_CURRXYWH, xx, yy, ww, hh);
  516.   wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
  517.   if (wp->x_off+wp->w > wp->wi_w) 
  518.   {
  519.     inc_x = wp->font->inc_x;
  520.     flag = 1;
  521.     wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  522.   }
  523.   if (wp->y_off+wp->h > wp->wi_h) 
  524.   {
  525.     inc_y = wp->font->inc_y;
  526.     flag = 1;
  527.     wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  528.   }
  529.   x1 = wp->m_off;
  530.   x2 = (wp->x - wp->x_off) & 15;
  531.   if (x1 != x2) 
  532.   {
  533.     c[0] = x1;
  534.     c[1] = wp->top_y;  /* displayed part of memory form starts here */
  535.     c[2] = x1 + wp->wi_w - 1;
  536.     c[3] = wp->wi_h - 1 + c[1];
  537.     c[4] = x2;
  538.     c[5] = c[1];
  539.     c[6] = x2 + wp->wi_w - 1;
  540.     c[7] = c[3];
  541.     vro_cpyfm(screen_handle, FM_COPY, c, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  542.     wp->m_off = x2;
  543.   }
  544.   if (flag)
  545.     w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  546.   setvslide(wp);
  547.   sethslide(wp);
  548. }
  549.  
  550. /*
  551.  * w_top makes win the top window.
  552.  */
  553.  
  554. void w_top(wp)
  555. struct wi_str *wp;
  556. {
  557.   wind_set(wp->aes_handle, WF_TOP, 0, 0, 0, 0);
  558.  
  559.   if (wlist == wp) return;  /* already top of list */
  560.  
  561.   /* unlink from its current place */
  562.   wp->next->prev = wp->prev;
  563.   wp->prev->next = wp->next;
  564.  
  565.   /* link into top */
  566.   wp->next = wlist;
  567.   wp->prev = wlist->prev;
  568.   wlist->prev->next = wp;
  569.   wlist->prev = wp;
  570.   wlist = wp;
  571. }
  572.  
  573. /*
  574.  * w_bottom finds the bottom window and puts it on top
  575.  */
  576.  
  577. void w_bottom()
  578. {
  579.   struct wi_str *wp;
  580.  
  581.   if (!wlist || wlist->next == wlist) return;
  582.   for (wp = wlist->next; wp->next != wlist; wp = wp->next)  /* do nothing */ ;
  583.   w_top(wp);
  584. }
  585.  
  586. /*
  587.  * w_hide puts the top window on the bottom.
  588.  * (a.k.a. "bury")
  589.  */
  590.  
  591. void w_hide()
  592. {
  593.   struct wi_str *wp, *oldtop;
  594.  
  595.   /* top all the windows, in order, from back to front, except the first. */
  596.   if (!wlist || wlist->next == wlist) return;  /* empty or singleton list */
  597.   oldtop = wlist;  /* window NOT to top */
  598.   for (wp = wlist->prev; wp != oldtop; wp = wp->prev)
  599.     wind_set(wp->aes_handle,WF_TOP, 0,0,0,0);
  600.  
  601.   /* move the top element from wlist to the end of wlist (easy!) */
  602.   wlist = wlist->next;
  603. }
  604.  
  605. #define TINYX 80
  606. #define TINYY 70
  607. /*
  608.  * w_shrink saves current size and location and shrinks to standard tiny size.
  609.  * The second from the top non-shrunk window is placed on top.
  610.  */
  611.  
  612. void w_shrink(wp)
  613. struct wi_str *wp;
  614. {
  615.   int wdes = wp->aes_handle;
  616.   int curx, cury, curw, curh;
  617.   static int slotcount;
  618.  
  619.   /*
  620.            * Don't shrink a window that is currently shrunk
  621.            */
  622.   wind_get(wdes, WF_CURRXYWH, &curx, &cury, &curw, &curh);
  623.   if (curw <= TINYX && cury <= TINYY)
  624.     return;
  625.  
  626.   if (wp->slotno == 0) wp->slotno = ++slotcount;
  627.  
  628.   /*
  629.            * By setting wp->fulled to one and the "previous" size to tiny,
  630.            * we're saying that the current size is the "full" size, and we
  631.            * want to "toggle to" the tiny size.
  632.            */
  633.   wp->fulled = 1;
  634.   wp->px = scr_x + (scr_w - TINYX + 2);
  635.   wp->py = scr_y + ((wp->slotno-1) * (TINYY + 2));
  636.   wp->pw = TINYX;
  637.   wp->ph = TINYY;
  638.  
  639.   /* ensure at least 10 dots of title bar on screen */
  640.   if (wp->py + 10 > scr_y + scr_h) 
  641.   {
  642.     wp->py = wp->py - scr_h + 10;
  643.     wp->px = scr_x + scr_w - TINYY * 2;
  644.   }
  645.   w_full(wp);
  646.  
  647.   /* now top the topmost window which isn't already tiny */
  648.  
  649.   wp = wlist;
  650.   do 
  651.   {
  652.     wdes = wp->aes_handle;
  653.     wind_get(wdes, WF_CURRXYWH, &curx, &cury, &curw, &curh);
  654.     if (curw > TINYX || curh > TINYY) 
  655.     {
  656.       w_full(wp);
  657.       w_top(wp);
  658.       return;
  659.     }
  660.     wp = wp->next;
  661.   } 
  662.   while (wp != wlist);
  663.  
  664.   /* no windows are not shrunk; just leave 'em */
  665. }
  666.  
  667. /* w_full toggles size and location between the current size and
  668.  * the "previous" size.
  669.  */
  670.  
  671. void w_full(wp)
  672. struct wi_str *wp;
  673. {
  674.   int x1, y1, w1, h1;
  675.   int x2, y2, w2, h2;
  676.   int full;
  677.   int wdes = wp->aes_handle;
  678.  
  679.   full = wp->fulled;
  680.  
  681.   /* if already full, set to "previous" size, else to full size */
  682.   if (full) 
  683.   {
  684.     x1 = wp->px;
  685.     y1 = wp->py;
  686.     w1 = wp->pw;
  687.     h1 = wp->ph;
  688.   }
  689.   else
  690.     wind_get(wdes, WF_FULLXYWH, &x1, &y1, &w1, &h1);
  691.  
  692.   wind_get(wdes, WF_CURRXYWH, &x2, &y2, &w2, &h2);
  693.   wp->px = x2;
  694.   wp->py = y2;
  695.   wp->pw = w2;
  696.   wp->ph = h2;
  697.   if (!fast) 
  698.   {
  699.     if (w2>=w1)
  700.       graf_growbox(x1, y1, w1, h1, x2, y2, w2, h2);
  701.     else
  702.       graf_shrinkbox(x1, y1, w1, h1, x2, y2, w2, h2);
  703.   }
  704.  
  705.   x2 = wp->x_off;
  706.   y2 = wp->y_off;
  707.   wp->x_off = wp->px_off;
  708.   wp->y_off = wp->py_off;
  709.   wp->px_off = x2;
  710.   wp->py_off = y2;
  711.  
  712.   w_move(wp, x1, y1, w1, h1);
  713.   w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  714.   wp->fulled = 1;
  715. }
  716.  
  717. void w_arrow(wp, arrow)
  718. struct wi_str *wp;
  719. int arrow;
  720. {
  721.   int inc_x = wp->font->inc_x;
  722.   int inc_y = wp->font->inc_y;
  723.  
  724.   switch (arrow) 
  725.   {
  726.   case 0:  /* page up */
  727.     wp->y_off -= wp->h/inc_y*inc_y;
  728.     goto y_upd;
  729.  
  730.   case 1:  /* page down */
  731.     wp->y_off += wp->h/inc_y*inc_y;
  732.     goto y_upd;
  733.  
  734.   case 2:  /* row up */
  735.     wp->y_off -= inc_y;
  736.     goto y_upd;
  737.  
  738.   case 3:  /* row down */
  739.     wp->y_off += inc_y;
  740.     goto y_upd;
  741.  
  742.   case 4:  /* page left */
  743.     wp->x_off -= wp->w/inc_x*inc_x;
  744.     goto x_upd;
  745.  
  746.   case 5:  /* page right */
  747.     wp->x_off += wp->w/inc_x*inc_x;
  748.     goto x_upd;
  749.  
  750.   case 6:  /* column left */
  751.     wp->x_off -= inc_x;
  752.     goto x_upd;
  753.  
  754.   case 7:  /* column right */
  755.     wp->x_off += inc_x;
  756.     goto x_upd;
  757.   }
  758.  
  759. x_upd:
  760.   if (wp->x_off<0) wp->x_off = 0; 
  761.   else
  762.     if (wp->x_off+wp->w > wp->wi_w) wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
  763.   sethslide(wp);
  764.   goto upd;
  765.  
  766. y_upd:
  767.   if (wp->y_off<0) wp->y_off = 0; 
  768.   else
  769.     if (wp->y_off+wp->h > wp->wi_h) wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
  770.   setvslide(wp);
  771.  
  772. upd:
  773.   w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  774. }
  775.  
  776. void w_slide(wp, hor, val)
  777. struct wi_str *wp;
  778. int hor, val;
  779. {
  780.   int tmp;
  781.  
  782.   if (hor) 
  783.   {
  784.     tmp = wp->font->inc_x;
  785.     wp->x_off = (int)(((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp);
  786.     sethslide(wp);
  787.   }
  788.   else 
  789.   {
  790.     tmp = wp->font->inc_y;
  791.     wp->y_off = (int)(((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp);
  792.     setvslide(wp);
  793.   }
  794.   w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  795. }
  796.  
  797. void sethslide(wp)
  798. struct wi_str *wp;
  799. {
  800.   int tmp;
  801.   int wdes = wp->aes_handle;
  802.  
  803.   if (wp->wi_style & HSLIDE) 
  804.   {
  805.     if (wp->wi_w == wp->w) tmp = 0;
  806.     else tmp = (int)((long)1000*wp->x_off/(wp->wi_w-wp->w));
  807.     if (tmp != wp->hspos) 
  808.     {
  809.       wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
  810.       wp->hspos = tmp;
  811.     }
  812.  
  813.     tmp = (int)((long)1000*wp->w/wp->wi_w);
  814.     if (tmp != wp->hssiz) 
  815.     {
  816.       wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
  817.       wp->hssiz = tmp;
  818.     }
  819.   }
  820. }
  821.  
  822. void setvslide(wp)
  823. struct wi_str *wp;
  824. {
  825.   int tmp;
  826.   int wdes = wp->aes_handle;
  827.  
  828.   if (wp->wi_style & VSLIDE) 
  829.   {
  830.     if (wp->wi_h == wp->h) tmp = 0;
  831.     else tmp = (int)((long)1000*wp->y_off/(wp->wi_h-wp->h));
  832.     if (tmp != wp->vspos) 
  833.     {
  834.       wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
  835.       wp->vspos = tmp;
  836.     }
  837.  
  838.     tmp = (int)((long)1000 * wp->h / wp->wi_h);
  839.     if (tmp != wp->vssiz) 
  840.     {
  841.       wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
  842.       wp->vssiz = tmp;
  843.     }
  844.   }
  845. }
  846.  
  847. /*
  848.  * flash the cursor in a window; if it's not the last one we flashed,
  849.  * un_flash that one
  850.  */
  851. void w_flash(wp, state)
  852. struct wi_str *wp;
  853. int state;
  854. {
  855.   static struct wi_str *wp_last = NULL;
  856.   int t[8];
  857.  
  858. /*  if (wp_last && wp != wp_last) w_flash(wp_last, 1);*/
  859.   wp_last = wp;
  860.   if (wp->curstate == state) return;
  861.   if (state == 2)
  862.     wp->curstate = !wp->curstate;
  863.   else
  864.     wp->curstate = state;
  865.   t[0] = t[4] = wp->cur_x + wp->m_off;
  866.   t[1] = t[5] = wp->cur_y;
  867.   t[2] = t[6] = t[0]+wp->font->inc_x-1;
  868.   t[3] = t[7] = t[1]+wp->font->inc_y-1;
  869.   vro_cpyfm(screen_handle, FM_INVERT, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  870.   w_update(wp, FM_COPY, wp->cur_x, wp->cur_y, wp->font->inc_x, wp->font->inc_y);
  871. }
  872.  
  873. /* w_output prints a string onto the window.  The string may
  874.  * contain control chars and escape sequences.  Its length is given,
  875.  * so you can even output NULs.
  876.  */
  877. void w_output(wp, ptr, charcount)
  878. struct wi_str *wp;
  879. unsigned char *ptr;
  880. short charcount;
  881. {
  882.   unsigned char ch;
  883.   int inc_x, cur_x;
  884.   int inc_y, cur_y;
  885.   int t[8];
  886.   int /*f_x, f_y,*/ f_mod;
  887.   int scrolled;  /* Number of scrolling operations delayed */
  888.   int xsiz, ysiz;/* Size in chars of terminal emulation for this window*/
  889.   register unsigned char *sptr;
  890.   register unsigned long *dptr;
  891.   register unsigned long mask;
  892.   register int shift;
  893.   register unsigned long valu;
  894.   int count = 0;
  895.   char * fdata;
  896.   long width;
  897.   char * wimfptr;
  898.   int moffincx;
  899.   int state;
  900.  
  901.   if (!wp->font || charcount == 0) return;
  902.   state = wp->state;
  903.   inc_x = wp->font->inc_x;
  904.   inc_y = wp->font->inc_y;
  905.   xsiz = wp->x_chrs;
  906.   ysiz = wp->y_chrs;
  907.   /*f_x = */cur_x = wp->cur_x;
  908.   /*f_y = */cur_y = wp->cur_y;
  909.  
  910.   /*
  911.            * This sets "hard update" any time the bottom N lines of the buffer are
  912.            * being used -- that is, the overflow below the visible screen. This is
  913.            * seven lines in 8 when you're doing glass-tty scrolling things.  This
  914.            * is wrong & slow.
  915.            */
  916.  
  917.   scrolled = wp->top_y/inc_y;
  918.  
  919.   fdata = wp->font->f_data;
  920.   width = 2 * wp->wi_mf.wwords;
  921.   wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
  922.   moffincx = wp->m_off + inc_x - 1;
  923.   f_mod = 0;
  924.  
  925.   if (wp->curstate) 
  926.   {
  927.     w_flash(wp, 0);
  928.   }
  929.  
  930.   while (charcount--) 
  931.   {
  932.     ch = *ptr++;
  933.     if(ch == CAN)
  934.     {
  935.      state = S_NORMAL;
  936.      continue;
  937.     }
  938.       if(ch < ' ') 
  939.       {  /* not printable character */
  940.                                     /*
  941.                                      * If you've modified the screen in this incarnation and you aren't
  942.                                      * "scrolled", update before any non-printing character.  This
  943.                                      * appears to call w_update for the line you're on, from the X you
  944.                                      * started from to the X you're at now.  I think this is
  945.                                      * inefficient, but I'm not sure yet.  If you're in insert mode,
  946.                                      * update the whole line from the starting X to the end of the
  947.                                      * line.
  948.                                      *
  949.                                      * I changed this to set "scrolled" if you get here and f_mod is
  950.                                      * TRUE.  That means simple updates on one line (no non-printing
  951.                                      * chars) don't happen in "scrolled" mode, but anything more
  952.                                      * complicated does.  This is also conditional on jerky_updates,
  953.                                      * which is the visual result.
  954.                                      */
  955.  
  956.         if (f_mod)
  957.         {
  958.          if(!jerky_updates) scrolled++;
  959.         }
  960.         switch (ch) 
  961.         {
  962.         case '\007':  /* Bell */
  963.           if (audibell) (void)Bconout(2, '\007');
  964.           if (visibell) 
  965.           {
  966.             w_redraw(wp, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
  967.             w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  968.             /* Should clear flag to prevent need for next update? */
  969.           }
  970.           break;
  971.  
  972.         case '\r':  /* Carriage Return */
  973.           cur_x = X0;
  974.           break;
  975.  
  976.         case '\b':  /* Backspace */
  977.           if (cur_x>X0) cur_x -= inc_x;
  978.           break;
  979.  
  980.         case '\n':  /* Newline */
  981.           if (cur_y + inc_y >= inc_y * (wp->bottomline + 1) + wp->top_y)
  982.           {
  983.             scrollup(wp, wp->topline, wp->bottomline - wp->topline, 1);
  984.           if (! scrolled)
  985.             w_update(wp, FM_COPY, X0, wp->topline * inc_y, xsiz * inc_x,
  986.             wp->top_y + (inc_y * (wp->bottomline - wp->topline + 1)));
  987.           }
  988.           else cur_y += inc_y;
  989.           if(wp->lfmode) cur_x = X0;
  990.           break;
  991.  
  992.         case '\t':  /* Tab */
  993.           cur_x = (((cur_x - X0)/inc_x/8 + 1))*inc_x*8+X0;
  994.           cur_x = min(cur_x, (inc_x * (xsiz-1)+X0)); 
  995.           break;
  996.  
  997.         case ENQ:  /* ENQ - get answer back */
  998.           sprintf(o_str,"TUW VT100");
  999.           o_len = (int)strlen(o_str);
  1000.           tcp_out(wp->pid,o_str,o_len);
  1001.           break;
  1002.         case SI:
  1003.           wp->chset = 0;
  1004.           break;
  1005.         case SO:
  1006.           wp->chset = 1;
  1007.           break;
  1008.         case '\033':  /* ESC */
  1009.           state = S_ESC;
  1010.           count = 0;  /* count is used for insert or delete line */
  1011.           break;
  1012.         }
  1013.         /*f_x = cur_x;
  1014.         f_y = cur_y;*/
  1015.       }
  1016.     else
  1017.     {
  1018.     switch (state) 
  1019.     {
  1020.     case S_NORMAL:
  1021.       if (ch >= ' ') 
  1022.       {
  1023.         if (wp->insmode) 
  1024.         {  /* open space for character */
  1025.           t[0] = cur_x + wp->m_off;
  1026.           t[1] = t[5] = cur_y;
  1027.           t[2] = (xsiz - 1) * inc_x + wp->m_off - 1;
  1028.           t[3] = t[7] = cur_y + inc_y - 1;
  1029.           t[4] = t[0] + inc_x;
  1030.           t[6] = t[2] + inc_x;
  1031.           vro_cpyfm(screen_handle, FM_COPY, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1032.         }
  1033.  
  1034.         /* paint the character (only if it's in range for this font) */
  1035.         if (ch < wp->font->nchars) 
  1036.         {
  1037.           ch &= 0x7f;
  1038.           if(wp->chset == 0)
  1039.           {
  1040.             if(wp->G0 == '0' && ch >= '_') ch -= '_';
  1041.           }
  1042.           else
  1043.             if(wp->G1 == '0' && ch >= '_') ch -= '_';
  1044.           sptr = (unsigned char *)(fdata+ch*16);
  1045.           dptr = (unsigned long *)(wimfptr + cur_y*width
  1046.               + (((moffincx + cur_x)>>4)<<1));
  1047.           shift = 15 - ((moffincx + cur_x)&15);
  1048.  
  1049.           /* to get overstrike, set mask to -1 */
  1050.           mask = (-1L << (shift+inc_x)) | ((1 << shift)-1);
  1051.           if (wp->inverse) 
  1052.           {
  1053.             for (count = inc_y; count; count--) 
  1054.             {
  1055.               valu = (((long)(*sptr++)) << shift) ^ ~mask;
  1056.               *dptr = (*dptr&mask)|valu;
  1057.               ((char *)dptr) += width;
  1058.             }
  1059.           }
  1060.           else 
  1061.           {
  1062.             for (count = inc_y; count; count--) 
  1063.             {
  1064.               valu = ((long)(*sptr++))<<shift;
  1065.               *dptr = (*dptr&mask)|valu;
  1066.               ((char *)dptr) += width;
  1067.             }
  1068.           }
  1069.         }
  1070.         cur_x += inc_x;
  1071.         f_mod = 1;
  1072.         if (cur_x >= inc_x * xsiz) 
  1073.         {  /* autowrap */
  1074.           cur_x -= inc_x;  /* back to last char position */
  1075.           if (wp->discard) 
  1076.           {
  1077.           }
  1078.           else 
  1079.           {
  1080.             if (cur_y + inc_y >= inc_y * (wp->bottomline + 1) + wp->top_y)
  1081.             {
  1082.               scrollup(wp, wp->topline, wp->bottomline - wp->topline, 1);
  1083.             if (! scrolled)
  1084.               w_update(wp, FM_COPY, X0, wp->topline * inc_y, xsiz * inc_x,
  1085.               wp->top_y + (inc_y * (wp->bottomline - wp->topline + 1)));
  1086.             }
  1087.             else cur_y += inc_y;
  1088.             cur_x = X0;
  1089.  
  1090.           /* cur_y += inc_y;
  1091.             if (cur_y >= wp->top_y + inc_y * ysiz) 
  1092.             {
  1093.               wp->top_y += inc_y;
  1094.               ++ scrolled;
  1095.             }
  1096.             if (! scrolled) 
  1097.             {
  1098.               w_update(wp, FM_COPY, f_x, f_y, cur_x-f_x, inc_y);
  1099.               f_mod = 0;
  1100.             }
  1101.             cur_x = X0;
  1102.  
  1103.             f_x = cur_x;
  1104.             f_y = cur_y;
  1105.           */}
  1106.         }
  1107.       } 
  1108.       break;
  1109.  
  1110.     case S_CHS0:
  1111.       wp->G0 = ch;
  1112.       state = S_NORMAL;
  1113.       break;
  1114.       
  1115.     case S_CHS1:
  1116.       wp->G1 = ch;
  1117.       state = S_NORMAL;
  1118.       break;
  1119.  
  1120.     case S_ESC:
  1121.       switch (ch) 
  1122.       {
  1123.       case '[':  /* CSI */
  1124.         state = S_CSI;
  1125.         wp->val1 = wp->val2 = wp->valcnt = 0;
  1126.         break;
  1127.       case '(':
  1128.         state = S_CHS0;
  1129.         break;
  1130.       case ')':
  1131.         state = S_CHS1;
  1132.         break;
  1133.       case '7':  /* AKP: save cursor location */
  1134.         wp->save_x = cur_x;
  1135.         wp->save_y = cur_y;
  1136.         state = S_NORMAL;
  1137.         break;
  1138.       case '8':  /* AKP: restore saved location */
  1139.         /*f_x = */cur_x = wp->save_x;
  1140.         /*f_x = */cur_y = wp->save_y;
  1141.         state = S_NORMAL;
  1142.         break;
  1143.       case '>':  /* reset keypad (numeric) mode */
  1144.         wp->keypad = 0;
  1145.         state = S_NORMAL;
  1146.         break;
  1147.       case '=':  /* set keypad (application) mode */
  1148.         wp->keypad = 1;
  1149.         state = S_NORMAL;
  1150.         break;
  1151.       case 'Z':  /* terminal ID */
  1152.         /* this is obsolete. use ESC [ c */
  1153.         state = S_NORMAL;
  1154.         break;
  1155.       case 'c':  /* reset to initial state */
  1156.         vt100_reset(wp);
  1157.         wp->discard = 1;
  1158.         state = S_NORMAL;
  1159.         break;
  1160.       case 'H':  /* set tab at current position */
  1161.         state = S_NORMAL;
  1162.         break;
  1163.       case 'E':  /* next line */
  1164.           cur_x = X0;
  1165.       case 'D':  /* index */
  1166.         cur_y += inc_y;
  1167.         if (cur_y >= inc_y * (wp->bottomline+1) + wp->top_y)
  1168.         {
  1169.           wp->top_y += inc_y;
  1170.           ++ scrolled;
  1171.         }
  1172.         state = S_NORMAL;
  1173.         break;
  1174.       case 'M':  /* Reverse Index (does possible reverse scroll) */
  1175.         if (cur_y != wp->top_y + (wp->topline * inc_y)) 
  1176.         {
  1177.           cur_y -= inc_y;
  1178.         }
  1179.         else
  1180.         {
  1181.           scrolldn(wp, cur_y/inc_y, wp->bottomline - wp->topline, 1);
  1182.           if (! scrolled)
  1183.             w_update(wp, FM_COPY, X0, cur_y, xsiz * inc_x,
  1184.             wp->top_y + (inc_y * (wp->bottomline - wp->topline + 1)));
  1185.         }
  1186.         state = S_NORMAL;
  1187.         break;
  1188.       case '#':
  1189.         state = S_ALIGN;
  1190.         break;
  1191.       default:  /* Unknown escape sequence */
  1192.         state = S_NORMAL;
  1193.         break;
  1194.       }
  1195.       break;
  1196.     case S_ALIGN:
  1197.       if(ch == '8')
  1198.       {
  1199.           cur_x = X0;
  1200.           cur_y = wp->top_y = Y0;
  1201.        do
  1202.        {
  1203.           sptr = (unsigned char *)(fdata+'E'*16);
  1204.           dptr = (unsigned long *)(wimfptr + cur_y*width
  1205.               + (((moffincx + cur_x)>>4)<<1));
  1206.           shift = 15 - ((moffincx + cur_x)&15);
  1207.  
  1208.           /* to get overstrike, set mask to -1 */
  1209.           mask = (-1L << (shift+inc_x)) | ((1 << shift)-1);
  1210.  
  1211.           for (count = inc_y; count; count--) 
  1212.           {
  1213.             valu = ((long)(*sptr++))<<shift;
  1214.             *dptr = (*dptr&mask)|valu;
  1215.             ((char *)dptr) += width;
  1216.           }
  1217.         cur_x += inc_x;
  1218.         f_mod = 1;
  1219.         if (cur_x > inc_x * xsiz) 
  1220.         { 
  1221.             cur_y += inc_y;
  1222.             cur_x = X0;
  1223.         }
  1224.        }
  1225.        while(cur_y < (Y0 + inc_y * ysiz));
  1226.  
  1227.        f_mod = 0;
  1228.        cur_x = /*f_x = */X0;
  1229.        cur_y = /*f_y = */Y0;
  1230.        w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1231.       }
  1232.       state = S_NORMAL;
  1233.       break;
  1234.     case S_CSI:
  1235.       wp->valcnt = 0;
  1236.       switch (ch) 
  1237.       {
  1238.       case '?':
  1239.         state = S_QUE;
  1240.         wp->val1 = 0;
  1241.         break;
  1242.       case '0':
  1243.       case '1':
  1244.       case '2':
  1245.       case '3':
  1246.       case '4':
  1247.       case '5':
  1248.       case '6':
  1249.       case '7':
  1250.       case '8':
  1251.       case '9':
  1252.         state = S_NUM1;
  1253.         wp->valcnt = 0;
  1254.         wp->val[0] = wp->val1 = ch - '0';
  1255.         break; 
  1256.       case 'm':  /* Exit Inverse */
  1257.         wp->inverse = 0;
  1258.         state = S_NORMAL;
  1259.         break;
  1260.       default:  /* other escape sequence, continue as if parameter 0 */
  1261.         state = S_NUM1;
  1262.         wp->valcnt = 0;
  1263.         wp->val[0] = 0;
  1264.         ptr--;
  1265.         charcount++;
  1266.         break;
  1267.       }
  1268.       break;
  1269.     case S_NUM1:
  1270.       switch (ch) 
  1271.       {
  1272.       case '0':
  1273.       case '1':
  1274.       case '2':
  1275.       case '3':
  1276.       case '4':
  1277.       case '5':
  1278.       case '6':
  1279.       case '7':
  1280.       case '8':
  1281.       case '9':
  1282.         wp->val1 = wp->val[0] = (wp->val1*10) + ch - '0';
  1283.         break; 
  1284.       case ';':
  1285.         state = S_NUM2;
  1286.         wp->valcnt = 1;
  1287.         wp->val[1] = 0;
  1288.         break;
  1289.       case 'J':
  1290.         switch(wp->val1)
  1291.         {
  1292.         case 0:  /* Clear to End of Screen */
  1293.           lineerase(wp, cur_y / inc_y + 1, ysiz - 1 + wp->top_y / inc_y);
  1294.           if (! scrolled)
  1295.             w_update(wp, FM_COPY, X0, cur_y + inc_y, xsiz*inc_x, ysiz*inc_y);
  1296.           t[0] = t[4] = cur_x + wp->m_off;
  1297.           t[1] = t[5] = cur_y;
  1298.           t[2] = t[6] = X0-1 + xsiz*inc_x +wp->m_off;
  1299.           t[3] = t[7] = cur_y+inc_y-1;
  1300.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1301.           if (! scrolled)
  1302.             w_update(wp, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
  1303.           state = S_NORMAL;
  1304.           break;
  1305.         case 1:  /* Clear from beginning of screen */
  1306.           if(cur_y >= inc_y) lineerase(wp, 0, cur_y/inc_y - 1);  /* clear top to this line */
  1307.           ++scrolled;
  1308.           t[0] = t[4] = wp->m_off;  /* init X */
  1309.           t[1] = t[5] = cur_y;  /* init Y */
  1310.           t[2] = t[6] = cur_x + wp->m_off + inc_x - 1;  /* final X */
  1311.           t[3] = t[7] = cur_y+inc_y-1;
  1312.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1313.           ++scrolled;
  1314.           state = S_NORMAL;
  1315.           break;
  1316.         case 2:  /* Clear whole Screen */
  1317.           /*f_x = */cur_x = X0;
  1318.           wp->top_y = /*f_y = */cur_y = Y0;
  1319.           wp->inverse = 0;
  1320.           wp->insmode = 0;
  1321.           lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  1322.           ++ scrolled;
  1323.           state = S_NORMAL;
  1324.           break;
  1325.         }
  1326.         break;
  1327.       case 'K':
  1328.         switch(wp->val1)
  1329.         {
  1330.         case 0:  /* Clear to End of Line */
  1331.           t[0] = t[4] = cur_x + wp->m_off;
  1332.           t[1] = t[5] = cur_y;
  1333.           t[2] = t[6] = X0-1 + xsiz*inc_x +wp->m_off;
  1334.           t[3] = t[7] = cur_y+inc_y-1;
  1335.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1336.           if (! scrolled)
  1337.             w_update(wp, FM_COPY, cur_x, cur_y, xsiz * inc_x - cur_x, inc_y);
  1338.           state = S_NORMAL;
  1339.           break;
  1340.         case 1:  /* Clear from beginning of line */
  1341.           t[0] = t[4] = wp->m_off;  /* init X */
  1342.           t[1] = t[5] = cur_y;  /* init Y */
  1343.           t[2] = t[6] = cur_x + wp->m_off + inc_x -1;  /* final X */
  1344.           t[3] = t[7] = cur_y+inc_y-1;
  1345.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1346.           ++scrolled;
  1347.           state = S_NORMAL;
  1348.           break;
  1349.         case 2:  /* erase entire line, cursor to left */
  1350.           t[0] = t[4] = wp->m_off;
  1351.           t[1] = t[5] = cur_y;
  1352.           t[2] = t[6] = X0-1 + xsiz*inc_x + wp->m_off;
  1353.           t[3] = t[7] = cur_y+inc_y-1;
  1354.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1355.           ++scrolled;
  1356.           cur_x = X0;
  1357.           state = S_NORMAL;
  1358.           break;
  1359.         }
  1360.         break;  
  1361.       case 'H':  /* special case cursor set */
  1362.       case 'f':
  1363.         if(wp->val1 != 0) wp->val1--;
  1364.         if(wp->origmode) wp->val1 += wp->topline;
  1365.         /*f_x = */cur_x = X0;
  1366.         /*f_y = */cur_y = wp->val1*inc_y + wp->top_y;
  1367.         state = S_NORMAL;
  1368.         break;
  1369.       case 'A':  /* Cursor Up */
  1370.         if(wp->val1 == 0) wp->val1 = 1;
  1371.         for(;wp->val1;wp->val1--)
  1372.         if(wp->origmode)
  1373.         {
  1374.           if (cur_y > wp->topline*inc_y + wp->top_y) 
  1375.           {
  1376.             cur_y -= inc_y;
  1377.           }
  1378.         }
  1379.         else
  1380.         {
  1381.           if (cur_y!=wp->top_y) 
  1382.           {
  1383.             cur_y -= inc_y;
  1384.           }
  1385.         }
  1386.         state = S_NORMAL;
  1387.         break;
  1388.       case 'B':  /* Cursor Down */
  1389.         if(wp->val1 == 0) wp->val1 = 1;
  1390.         for(;wp->val1;wp->val1--)
  1391.         if(wp->origmode)
  1392.         {
  1393.           if ((cur_y + inc_y) < (wp->bottomline + 1)*inc_y) 
  1394.           {
  1395.             cur_y += inc_y;
  1396.           }
  1397.         }
  1398.         else
  1399.         {
  1400.           if ((cur_y + inc_y) < (wp->top_y + (inc_y * ysiz))) 
  1401.           {
  1402.             cur_y += inc_y;
  1403.           }
  1404.         }
  1405.         state = S_NORMAL;
  1406.         break;
  1407.       case 'C':  /* Cursor Right */
  1408.         if(wp->val1 == 0) wp->val1 = 1;
  1409.         for(;wp->val1;wp->val1--)
  1410.           if (cur_x < (xsiz - 1) * inc_x) cur_x += inc_x;
  1411.         state = S_NORMAL;
  1412.         break;
  1413.       case 'D':  /* Cursor Left */
  1414.         if(wp->val1 == 0) wp->val1 = 1;
  1415.         for(;wp->val1;wp->val1--)
  1416.           if (cur_x > X0) cur_x -= inc_x;
  1417.         state = S_NORMAL;
  1418.         break;
  1419.       case 'L':  /* Insert Line */
  1420.         if(wp->val1 == 0) wp->val1 = 1;
  1421.         wp->val1 = min(wp->val1, cur_y/inc_y - wp->topline);
  1422.         scrolldn(wp, cur_y/inc_y, (wp->bottomline + 1) - (cur_y - wp->top_y + Y0)/inc_y - wp->val1, wp->val1);
  1423.         if (! scrolled)
  1424.           w_update(wp, FM_COPY, X0, cur_y, xsiz * inc_x,
  1425.           (wp->bottomline + 1) * inc_y - cur_y + wp->top_y - Y0);
  1426.         state = S_NORMAL;
  1427.         break;
  1428.       case 'M':  /* Delete Line */
  1429.         if(wp->val1 == 0) wp->val1 = 1;
  1430.         wp->val1 = min(wp->val1, wp->bottomline - cur_y/inc_y);
  1431.         scrollup(wp, cur_y / inc_y,
  1432.         wp->bottomline - (cur_y - wp->top_y + Y0)/inc_y - wp->val1 + 1, wp->val1);
  1433.         if (! scrolled)
  1434.           w_update(wp, FM_COPY, X0, cur_y, xsiz * inc_x,
  1435.           (wp->bottomline + 1) * inc_y - cur_y + wp->top_y - Y0);
  1436.         state = S_NORMAL;
  1437.         break;
  1438.       case 'P':  /* Delete Character */
  1439.         if(wp->val1 == 0) wp->val1 = 1;
  1440.         for(;wp->val1;wp->val1--)
  1441.         {
  1442.           t[0] = cur_x + inc_x + wp->m_off;
  1443.           t[1] = t[5] = cur_y;
  1444.           t[2] = X0 - 1 + xsiz * inc_x + wp->m_off;
  1445.           t[3] = t[7] = cur_y+inc_y - 1;
  1446.           t[4] = t[0] - inc_x;
  1447.           t[6] = t[2] - inc_x;
  1448.           vro_cpyfm(screen_handle, FM_COPY, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1449.           t[0] = t[4] = X0 + (xsiz - 1) * inc_x + wp->m_off;
  1450.           t[2] = t[6] = t[0] + inc_x - 1;
  1451.           vro_cpyfm(screen_handle, FM_CLEAR, t, (MFDB*)&wp->wi_mf, (MFDB*)&wp->wi_mf);
  1452.         }
  1453.         if (! scrolled)
  1454.           w_update(wp, FM_COPY, cur_x, cur_y, xsiz * inc_x - (cur_x - X0),
  1455.           inc_y);
  1456.         state = S_NORMAL;
  1457.         break;
  1458.       case 'h':  /* Insert Mode */
  1459.         switch(wp->val1)
  1460.         {
  1461.         case 4:
  1462.           wp->insmode = 1;
  1463.           break;
  1464.         case 20:
  1465.           wp->lfmode = 1;
  1466.           state = S_NORMAL;
  1467.           break;
  1468.         }
  1469.         state = S_NORMAL;
  1470.         break;
  1471.       case 'l':  /* End Insert */
  1472.         switch(wp->val1)
  1473.         {
  1474.         case 4:
  1475.           wp->insmode = 0;
  1476.           break;
  1477.         case 20:
  1478.           wp->lfmode = 0;
  1479.           state = S_NORMAL;
  1480.           break;
  1481.         }
  1482.         state = S_NORMAL;
  1483.         break;
  1484.       case 'm':
  1485.         switch(wp->val1)
  1486.         {
  1487.         case 0:  /* Exit Inverse */
  1488.           wp->inverse = 0;
  1489.           break;
  1490.         default:
  1491.           wp->inverse = 1;
  1492.         }
  1493.         state = S_NORMAL;
  1494.         break;
  1495.       case 'n':
  1496.        switch(wp->val1)
  1497.        {
  1498.          case 5:
  1499.            sprintf(o_str,"\033[0n");
  1500.            o_len = (int)strlen(o_str);
  1501.            tcp_out(wp->pid,o_str,o_len);
  1502.          break;
  1503.          case 6:
  1504.            wp->val1 = 1 + (cur_y - wp->top_y)/inc_y;
  1505.            wp->val2 = 1 + (cur_x - X0)/inc_x;
  1506.            sprintf(o_str,"\033[%d;%dR",wp->val1,wp->val2);
  1507.            o_len = (int)strlen(o_str);
  1508.            tcp_out(wp->pid,o_str,o_len);
  1509.          break;
  1510.        }
  1511.        break; 
  1512.       case 'c':
  1513.        sprintf(o_str,"\033[?1;2c");
  1514.        o_len = (int)strlen(o_str);
  1515.        tcp_out(wp->pid,o_str,o_len);
  1516.        break;
  1517.       default:
  1518.         state = S_NORMAL;
  1519.         break;
  1520.       }
  1521.       break;
  1522.     case S_QUE:
  1523.       switch(ch)
  1524.       {
  1525.       case '0':
  1526.       case '1':
  1527.       case '2':
  1528.       case '3':
  1529.       case '4':
  1530.       case '5':
  1531.       case '6':
  1532.       case '7':
  1533.       case '8':
  1534.       case '9':
  1535.         wp->val1 = (wp->val1*10) + ch - '0';
  1536.         break; 
  1537.       case 'l':
  1538.         switch(wp->val1)
  1539.         {
  1540.         case 1:
  1541.           wp->curskey = 0;
  1542.           state = S_NORMAL;
  1543.           break;
  1544.         case 3:
  1545.           if (w_resize(wp, 80, 24, wp->sliders, wp->titles, 0));
  1546.           xsiz = 80;
  1547.           wp = wlist;
  1548.           wp->colwidth = 0;
  1549.           /*f_x = */cur_x = X0;
  1550.           /*f_y = */cur_y = Y0;
  1551.           width = 2 * wp->wi_mf.wwords;
  1552.           wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
  1553.           moffincx = wp->m_off + inc_x - 1;
  1554.           lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  1555.           ++ scrolled;
  1556.           state = S_NORMAL;
  1557.           break;
  1558.         case 4:
  1559.           wp->smooth = 0;
  1560.           state = S_NORMAL;
  1561.           break;
  1562.         case 5:
  1563.           wp->fgbg[0] = (ncolors-1);
  1564.           wp->fgbg[1] = 0;
  1565.           state = S_NORMAL;
  1566.           scrolled++;  /* force a hard update */
  1567.           break;
  1568.         case 6:
  1569.           wp->origmode = 0;
  1570.           /*f_y = */cur_y = wp->val1*inc_y + wp->top_y;
  1571.           /*f_x = */cur_x = X0;
  1572.           state = S_NORMAL;
  1573.           break;
  1574.         case 7:
  1575.           wp->discard = 1;
  1576.           state = S_NORMAL;
  1577.           break;
  1578.         case 8:
  1579.           wp->repeat = 0;
  1580.           state = S_NORMAL;
  1581.           break;
  1582.         }
  1583.         break;
  1584.       case 'h':
  1585.         switch(wp->val1)
  1586.         {
  1587.         case 1:
  1588.           wp->curskey = 1;
  1589.           state = S_NORMAL;
  1590.           break;
  1591.         case 3:
  1592.           if (w_resize(wp, 132, 24, wp->sliders, wp->titles, 0));
  1593.           xsiz = 132;
  1594.           wp = wlist;
  1595.           wp->colwidth = 1;
  1596.           /*f_x = */cur_x = X0;
  1597.           /*f_y = */cur_y = Y0;
  1598.           width = 2 * wp->wi_mf.wwords;
  1599.           wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
  1600.           moffincx = wp->m_off + inc_x - 1;
  1601.           lineerase(wp, 0, ysiz - 1 + MAXSCROLLED);
  1602.           ++ scrolled;
  1603.           state = S_NORMAL;
  1604.           break;
  1605.         case 4:
  1606.           wp->smooth = 1;
  1607.           state = S_NORMAL;
  1608.           break;
  1609.         case 5:
  1610.           wp->fgbg[0] = 0;
  1611.           wp->fgbg[1] = (ncolors-1);
  1612.           state = S_NORMAL;
  1613.           scrolled++;  /* force a hard update */
  1614.           break;
  1615.         case 6:
  1616.           wp->origmode = 1;
  1617.           state = S_NORMAL;
  1618.           /*f_y = */cur_y = wp->val1*inc_y + wp->top_y;
  1619.           /*f_x = */cur_x = X0;
  1620.           break;
  1621.         case 7:
  1622.           wp->discard = 0;
  1623.           state = S_NORMAL;
  1624.           break;
  1625.         case 8:
  1626.           wp->repeat = 1;
  1627.           state = S_NORMAL;
  1628.           break;
  1629.         }
  1630.       }
  1631.       break;
  1632.     case S_NUM2:
  1633.       switch (ch) 
  1634.       {
  1635.       case '0':
  1636.       case '1':
  1637.       case '2':
  1638.       case '3':
  1639.       case '4':
  1640.       case '5':
  1641.       case '6':
  1642.       case '7':
  1643.       case '8':
  1644.       case '9':
  1645.         wp->val2 = wp->val[wp->valcnt] = (wp->val[wp->valcnt]*10) + ch - '0';
  1646.         break; 
  1647.       case ';':
  1648.         if(wp->valcnt < 8) wp->valcnt++;
  1649.         wp->val[wp->valcnt] = 0;
  1650.         break;
  1651.       case 'H':
  1652.       case 'f':
  1653.         if(wp->val1 != 0) wp->val1--;
  1654.         if(wp->val2 != 0) wp->val2--;
  1655.         if(wp->origmode) wp->val1 += wp->topline;
  1656.         if (wp->val1 > ysiz-1) wp->val1 = ysiz-1;
  1657.         if(wp->origmode && wp->val1 > wp->bottomline) wp->val1 = wp->bottomline;
  1658.         /*f_y = */cur_y = wp->val1*inc_y + wp->top_y;
  1659.         if (wp->val2 > xsiz-1) wp->val2 = xsiz-1;
  1660.         /*f_x = */cur_x = wp->val2*inc_x +X0;
  1661.         state = S_NORMAL;
  1662.         break;
  1663.       case 'r':
  1664.         /* change scrolling region */
  1665.         if(wp->val1 == 0 && wp->val2 == 0) /* empty resets to whole screen */
  1666.         {
  1667.          wp->val1 = 1;
  1668.          wp->val2 = 24;
  1669.         }
  1670.         if(wp->val1 != 0) wp->val1--;
  1671.         if(wp->val2 != 0) wp->val2--;
  1672.         wp->topline = wp->val1;
  1673.         wp->bottomline = wp->val2;
  1674.         /*f_y = */cur_y = wp->val1*inc_y + wp->top_y;
  1675.         /*f_x = */cur_x = X0;
  1676.         state = S_NORMAL;
  1677.         break;
  1678.       case 'm':
  1679.       {
  1680.         int i;
  1681.         for(i=0;i <= wp->valcnt;i++)
  1682.         {
  1683.           switch(wp->val[i])
  1684.           {
  1685.           case 0:  /* Exit Inverse */
  1686.             wp->inverse = 0;
  1687.             break;
  1688.           default:
  1689.             wp->inverse = 1;
  1690.           }
  1691.         }
  1692.         state = S_NORMAL;
  1693.         break;
  1694.       }
  1695.       default:
  1696.         state = S_NORMAL;
  1697.         break;
  1698.       }
  1699.     }  /* end switch on state */
  1700.     }
  1701.     if (scrolled >= MAXSCROLLED) 
  1702.     {
  1703.       if (wp->top_y != Y0) 
  1704.       {
  1705.         scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1706.         wp->top_y = Y0;
  1707.         /*f_y = */cur_y = Y0 + (ysiz - 1) * inc_y;
  1708.       }
  1709.       w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1710.       scrolled = 0;
  1711.     }
  1712.   }  /* end while loop for each character */
  1713.  
  1714.              /*
  1715.              * "scrolled" is true if you need to do a hard update, where multiple
  1716.              * lines may have changed.  This used to actually align the virtual
  1717.              * screen with the physical screen only when scrolled >= MAXSCROLLED, but
  1718.              * this meant that seven lines out of eight got hard updates for every
  1719.              * char when typing on a scrolling TTY.  So I align them every time.
  1720.              */
  1721.   if (scrolled) 
  1722.   {
  1723.     if (wp->top_y != Y0) 
  1724.     {
  1725.       scrollup(wp, 0, ysiz, wp->top_y/inc_y);
  1726.       cur_y -= (wp->top_y - Y0);
  1727.       wp->top_y = Y0;
  1728.     }
  1729.   }
  1730.   w_redraw(wp, FM_COPY, wp->x, wp->y, wp->w, wp->h);
  1731.   wp->cur_x = cur_x;
  1732.   wp->cur_y = cur_y;
  1733.   wp->state = state;
  1734.   w_flash(wp, 1);
  1735. }
  1736.  
  1737. void lineerase(wp, first, last)
  1738. register struct wi_str *wp;
  1739. int first, last;
  1740. {
  1741.   register short *p;
  1742.   register long *lp;
  1743.   long count;
  1744.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1745.  
  1746.   p = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords - 1;
  1747.   count = (last-first+1)*linespace;
  1748.   lp = (long *)p;
  1749.   while (count > 7)
  1750.   {
  1751.     *lp++ = 0;
  1752.     *lp++ = 0;
  1753.     *lp++ = 0;
  1754.     *lp++ = 0;
  1755.     count -= 8;
  1756.   }
  1757.   p = (short *)lp;
  1758.   while (--count >= 0)
  1759.     *++p = 0;
  1760. }
  1761.  
  1762. void scrollup(wp, first, nlines, amount)
  1763. register struct wi_str *wp;
  1764. int first, nlines, amount;
  1765. {
  1766.   register short *p1, *p2;
  1767.   register long *lp1, *lp2;
  1768.   register long count;
  1769.   int linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1770.  
  1771.   p1 = wp->wi_mf.ptr + first*linespace + Y0*wp->wi_mf.wwords;
  1772.   p2 = p1 + linespace * amount;
  1773.   count = (long)(nlines)*linespace;
  1774.   lp1 = (long *)p1;
  1775.   lp2 = (long *)p2;
  1776.   while (count > 15)
  1777.   {
  1778.     *lp1++ = *lp2++;
  1779.     *lp1++ = *lp2++;
  1780.     *lp1++ = *lp2++;
  1781.     *lp1++ = *lp2++;
  1782.     *lp1++ = *lp2++;
  1783.     *lp1++ = *lp2++;
  1784.     *lp1++ = *lp2++;
  1785.     *lp1++ = *lp2++;
  1786.     count -= 16;
  1787.   }
  1788.   p1 = (short *)lp1;
  1789.   p2 = (short *)lp2;
  1790.   while (--count >= 0)
  1791.     *(p1++) = *(p2++);
  1792.   count = linespace * amount;
  1793.   lp1 = (long *)p1;
  1794.   while (count > 7)
  1795.   {
  1796.     *lp1++ = 0;
  1797.     *lp1++ = 0;
  1798.     *lp1++ = 0;
  1799.     *lp1++ = 0;
  1800.     count -= 8;
  1801.   }
  1802.   p1 = (short *)lp1;
  1803.   while (--count >= 0)
  1804.     *(p1++) = 0;
  1805. }
  1806.  
  1807. void scrolldn(wp, first, nlines, amount)
  1808. register struct wi_str *wp;
  1809. int first, nlines, amount;
  1810. {
  1811.   register short *p1, *p2;
  1812.   register long *lp1, *lp2;
  1813.   register long count;
  1814.   long linespace = wp->wi_mf.wwords*wp->font->inc_y;
  1815.  
  1816.   p1 = wp->wi_mf.ptr + (nlines+first+amount)*linespace + Y0*wp->wi_mf.wwords;
  1817.  
  1818.   p2 = p1 - linespace * amount;
  1819.   count = (long)(nlines)*linespace;
  1820.   lp2 = (long *)p2;
  1821.   lp1 = (long *)p1;
  1822.   while (count > 15)
  1823.   {
  1824.     *--lp1 = *--lp2;
  1825.     *--lp1 = *--lp2;
  1826.     *--lp1 = *--lp2;
  1827.     *--lp1 = *--lp2;
  1828.     *--lp1 = *--lp2;
  1829.     *--lp1 = *--lp2;
  1830.     *--lp1 = *--lp2;
  1831.     *--lp1 = *--lp2;
  1832.     count -= 16;
  1833.   }
  1834.   p1 = (short *)lp1;
  1835.   p2 = (short *)lp2;
  1836.   while (--count >= 0)
  1837.     *--p1 = *--p2;
  1838.   count = linespace * amount;
  1839.   lp1 = (long *)p1;
  1840.   while (count > 7)
  1841.   {
  1842.     *--lp1 = 0L;
  1843.     *--lp1 = 0L;
  1844.     *--lp1 = 0L;
  1845.     *--lp1 = 0L;
  1846.     count -= 8;
  1847.   }
  1848.   p1 = (short *)lp1;
  1849.   while (--count >= 0)
  1850.     *--p1 = 0;
  1851. }
  1852. /* -------------------------------------------------------------------- */
  1853. /*       boolean rc_intersect( GRECT *r1, GRECT *r2 );                  */
  1854. /*                                                                      */
  1855. /*       Berechnung der Schnittfläche zweier Rechtecke.                 */
  1856. /*                                                                      */
  1857. /*       -> r1, r2               Pointer auf Rechteckstruktur.          */
  1858. /*                                                                      */
  1859. /*       <-                      TRUE  falls sich die Rechtecke         */
  1860. /*                                     schneiden,                       */
  1861. /*                               FALSE sonst.                           */
  1862. /* -------------------------------------------------------------------- */
  1863.  
  1864. int rc_intersect( GRECT *r1, GRECT *r2 )
  1865. {
  1866.   int x, y, w, h;
  1867.  
  1868.   x = max( r2->g_x, r1->g_x );
  1869.   y = max( r2->g_y, r1->g_y );
  1870.   w = min( r2->g_x + r2->g_w, r1->g_x + r1->g_w );
  1871.   h = min( r2->g_y + r2->g_h, r1->g_y + r1->g_h );
  1872.  
  1873.   r2->g_x = x;
  1874.   r2->g_y = y;
  1875.   r2->g_w = w - x;
  1876.   r2->g_h = h - y;
  1877.  
  1878.   return (((w > x) && (h > y) ) );
  1879. }
  1880.  
  1881. /*------------------------------*/
  1882. /*    vt100_reset        */
  1883. /*------------------------------*/
  1884. void vt100_reset (struct wi_str *wp)
  1885. {
  1886.   wp->repeat = 1;
  1887.   wp->curskey = 0;
  1888.   wp->keypad = 0;
  1889.   wp->topline = 0;
  1890.   wp->bottomline = wp->y_chrs-1;
  1891.   wp->colwidth = 0;
  1892.   wp->smooth = 0;
  1893.   wp->origmode = 0;
  1894.   wp->lfmode = 0;
  1895.   return;
  1896. }
  1897.  
  1898.